package net.qhzw.vip.qiyu.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import net.qhzw.vip.qiyu.entity.*;
import net.qhzw.vip.qiyu.handler.ApiException;
import net.qhzw.vip.qiyu.handler.MyException;
import net.qhzw.vip.qiyu.mapper.DtsCarRetreatMapper;
import net.qhzw.vip.qiyu.model.DtsCarRetreatVo;
import net.qhzw.vip.qiyu.model.ForRetForm;
import net.qhzw.vip.qiyu.model.RetreatDetailed;
import net.qhzw.vip.qiyu.service.*;
import net.qhzw.vip.qiyu.util.MyDateUtils;
import net.qhzw.vip.qiyu.util.SecurityUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class DtsCarRetreatServiceImpl extends ServiceImpl<DtsCarRetreatMapper, DtsCarRetreat>
        implements DtsCarRetreatService {

    @Autowired
    private DtsCarRetreatMapper dtsCarRetreatMapper;

    @Autowired
    private DtsUserService dtsUserService;

    @Autowired
    private DtsCarRentalService dtsCarRentalService;

    @Autowired
    private RepairMaintService repairMaintService;

    @Autowired
    private DtsCarRetreatMaintService dtsCarRetreatMaintService;

    @Autowired
    private RepairCodeService repairCodeService;

    @Autowired
    private SysCommunityService sysCommunityService;

    @Autowired
    private DtsUserDeductionService dtsUserDeductionService;

    @Autowired
    private GuaranteeCompanyService guaranteeCompanyService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private GuaranteeUserService guaranteeUserService;

    @Autowired
    private PayService payService;

    @Autowired
    private DtsCarRentalRefundService carRentalRefundService;

    @Autowired
    private DtsUserBillService dtsUserBillService;

    @Autowired
    private SysUserTopupOrderService sysUserTopupOrderService;

    @Autowired
    private DtsCarTransferService dtsCarTransferService;

    /***
     * 退车费用分页列表查询
     * @param page
     * @return
     */
    @Override
    public Map<String, Object> findByPage(Page<DtsCarRetreat> page, String idCard, String mobile, String realName, Long siteId, Long shopId) {
        //过滤当前登录人数据
        Long userId = SecurityUtils.getUserId();
        SysUser user = sysUserService.getById(userId);
        if (user == null || user.getCommunityId() == null) {
            return new HashMap<>();
        }
        Long communityId = null;
        if (user.getCommunityId() != 1L) {
            communityId = user.getCommunityId();
        }
        PageHelper.startPage((int) page.getCurrent(), (int) page.getSize());
        List<DtsCarRetreatVo> dtsCarRetreatVoList = dtsCarRetreatMapper.findByPage(idCard, mobile, realName, siteId, communityId, shopId);
        PageInfo<DtsCarRetreatVo> pageInfo = new PageInfo<>(dtsCarRetreatVoList);
        List<DtsCarRetreatVo> records = pageInfo.getList();
        if (!CollectionUtils.isEmpty(records)) {
            for (DtsCarRetreatVo record : records) {
                List<RepairMaint> maintList = getRepairMaintByRetreatId(Arrays.asList(record.getId()));
                BigDecimal price = new BigDecimal("0");
                if (!CollectionUtils.isEmpty(maintList)) {
                    record.setRepairMaints(maintList);
                    for (RepairMaint repairMaint : maintList) {
                        price = price.add(repairMaint.getPrice());
                    }
                }
                record.setMaintSum(price);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("total", (int) pageInfo.getTotal());
        result.put("records", records);
        return result;
    }


    /***
     * 查询配件价格
     * @param idList
     * @return
     */
    private List<RepairMaint> getRepairMaintByRetreatId(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return new ArrayList<RepairMaint>();
        }
        return repairMaintService.getRepairMaintByRetreatId(idList);
    }

    /***
     * 退车费用清单
     * @param forRetForm
     * @return
     */
    @Override
    public Map<String, Object> retFeeLst(ForRetForm forRetForm, Long shopId) {
        Map<String, Object> result = new HashMap<>();
        DtsCarRental dtsCarRental = dtsCarRentalService.getById(forRetForm.getCarRentalId());
        if (dtsCarRental.getStatus().intValue() != 3) {
            throw new MyException("租车申请未通过!");
        }
        if (dtsCarRental.getLease() == 2 && !CollectionUtils.isEmpty(forRetForm.getRepairMaintIds())){
            throw new MyException("您租凭的电池,没有该配件规格!");
        }
        //审核通过时间
        Date approvalTime = dtsCarRental.getApprovalTime();
        //租车押金
        BigDecimal deposit = dtsCarRental.getDeposit();
        DtsUser user = dtsUserService.getById(dtsCarRental.getUserId());
        //租车天数
        long days = 0;
        //用户余额
        BigDecimal balance = user.getBalance();
        //押金 + 用户余额 + 配件损坏费用 + 其他费用
        BigDecimal othrFee = new BigDecimal("0");
        if (forRetForm.getOthrFee() != null) {
            othrFee = forRetForm.getOthrFee();
        }
        BigDecimal cost = null;
        BigDecimal totalCost = null;
        //获取配件列表
        BigDecimal maintSum = getRepairFees(forRetForm.getRepairMaintIds());
        LambdaQueryWrapper<DtsCarRetreat> queryWrapper = new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getCarRentalId, forRetForm.getCarRentalId());
        DtsCarRetreat carRetreat = null;
        int count = count(queryWrapper);
        //支付码
        String payCode = "";
        days = MyDateUtils.daysBetween(approvalTime, new Date());
        cost = dtsCarRental.getDeposit().add(balance).subtract(maintSum).subtract(othrFee);
        totalCost = cost;
        //保存退款记录
        long id = IdWorker.getId();
        DtsCarRetreat dtsCarRetreat = new DtsCarRetreat();
        dtsCarRetreat.setId(id);
        dtsCarRetreat.setCarRentalId(forRetForm.getCarRentalId());
        dtsCarRetreat.setCost(totalCost);
        dtsCarRetreat.setUserId(dtsCarRental.getUserId());
        dtsCarRetreat.setRentalBalance(balance);
        dtsCarRetreat.setRetreatStatus(1);
        dtsCarRetreat.setStatus((byte) 0);
        dtsCarRetreat.setReturnFee(cost);
        dtsCarRetreat.setShopId(shopId);
        dtsCarRetreat.setOthrFee(othrFee);
        dtsCarRetreat.setRepairFee(maintSum);
        if (count > 0) {
            if (cost.compareTo(new BigDecimal(0)) == -1) {
                payCode = payService.carCarRetreatPay(dtsCarRental.getShopId(), forRetForm.getCarRentalId(), cost, dtsCarRental.getId());
            }
            update(dtsCarRetreat, queryWrapper);
        } else {
            if (cost.compareTo(new BigDecimal(0)) == -1) {
                payCode = payService.carCarRetreatPay(dtsCarRental.getShopId(), forRetForm.getCarRentalId(), cost, dtsCarRental.getId());
            }
            saveDtsCarRetreatMaint(forRetForm.getRepairMaintIds(), id);
            save(dtsCarRetreat);
        }
        result.put("maintSum", (BigDecimal) maintSum);
        result.put("othrFee", (BigDecimal) othrFee);
        result.put("carRentalDays", (int) days);
        result.put("deposit", (BigDecimal) deposit);
        result.put("userBalance", (BigDecimal) balance);
        result.put("cost", (BigDecimal) cost);
        result.put("payCode", (String) payCode);
        return result;
    }

    private byte getFeeStatus(double doubleValue) {
        if (doubleValue > 0) {
            return (byte) 2;
        } else {
            return (byte) 3;
        }
    }


    /***
     * 退车申请
     * @param forRetForm
     * @return
     */
    @Override
    public boolean appForRet(ForRetForm forRetForm) {
        checke(forRetForm);
        Long rentalId = forRetForm.getCarRentalId();
        DtsCarRental dtsCarRental = dtsCarRentalService.getById(rentalId);
        LambdaQueryWrapper<DtsCarRetreat> queryWrapper = new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getCarRentalId, rentalId);
        //维修费用
        List<Long> maintIds = forRetForm.getRepairMaintIds();
        DtsCarRetreat carRetreat = new DtsCarRetreat();
        BeanUtils.copyProperties(forRetForm, carRetreat);
        carRetreat.setShopId(dtsCarRental.getShopId());
        carRetreat.setAdminId(SecurityUtils.getUserId());
        carRetreat.setCommunityId(getCommunityId(SecurityUtils.getUserId()));
        carRetreat.setRepairCodeId(dtsCarRental.getRepairCodeId());
        carRetreat.setUserId(dtsCarRental.getUserId());
        carRetreat.setCreated(new Date());
        carRetreat.setGuaranteeCompanyId(dtsCarRental.getGuaranteeCompanyId());
        carRetreat.setRentalBalance(getUserbalance(forRetForm.getCarRentalId()));
        carRetreat.setStatus((byte) 1);
        //退车
        if (dtsCarRental.getLease().intValue() == 1) {
            Long repairCodeId = dtsCarRental.getRepairCodeId();
            Long communityId = dtsCarRental.getCommunityId();
            returnCar(repairCodeId, communityId, maintIds);
        }
        byte status = 1;
        byte retreatStatus = 2;
        carRetreat.setRetreatStatus(retreatStatus);
        carRetreat.setStatus(status);
        return update(carRetreat, queryWrapper);
    }

    /**
     * 还车
     *
     * @param repairCodeId
     * @param communityId
     * @param maintIds
     */
    private void returnCar(Long repairCodeId, Long communityId, List<Long> maintIds) {
        RepairCode repairCode = new RepairCode();
        repairCode.setId(repairCodeId);
        repairCode.setVehicleBelongs(communityId);
        repairCode.setRentUser(-1L);
        byte vehicleStatus = 1;
        String unusualLocation = "";
        if (!CollectionUtils.isEmpty(maintIds)) {
            List<RepairMaint> maints = repairMaintService.listByIds(maintIds);
            if (!CollectionUtils.isEmpty(maints)) {
                vehicleStatus = 2;
                List<String> names = maints.stream().map(RepairMaint::getName).collect(Collectors.toList());
                unusualLocation = "损坏部位: " + names.toString();
            }
        }
        repairCode.setVehicleStatus(vehicleStatus);
        repairCode.setUnusualLocation(unusualLocation);
        repairCodeService.updateById(repairCode);


    }

    /**
     * 退款
     *
     * @param forRetForm
     * @param dtsCarRental
     */
    private void refund(ForRetForm forRetForm, DtsCarRental dtsCarRental) {
        //获取配件列表
        List<RepairMaint> repairMaintList = getRepairMaintList(forRetForm.getRepairMaintIds());
        BigDecimal maintSum = new BigDecimal("0");
        if (!CollectionUtils.isEmpty(repairMaintList)) {
            for (RepairMaint repairMaint : repairMaintList) {
                maintSum = maintSum.add(repairMaint.getPrice());
            }
        }
        long days = MyDateUtils.daysBetween(dtsCarRental.getPayTime(), new Date());
        BigDecimal cost = dtsCarRental.getAdvanceRcptRent()
                .add(dtsCarRental.getDeposit())
                .add(dtsCarRental.getRent())
                .subtract(maintSum)
                .subtract(forRetForm.getOthrFee())
                .subtract(dtsCarRental.getDayRent().multiply(new BigDecimal(days + 1)));
        if (cost.compareTo(new BigDecimal(0)) == 1 && dtsCarRental.getIsPayed().intValue() == 1) {
            //退款操作
            List<DtsCarRentalRefund> refunds = carRentalRefundService.list(new LambdaQueryWrapper<DtsCarRentalRefund>()
                    .eq(DtsCarRentalRefund::getOrderId, dtsCarRental.getId())
                    .last("ORDER BY created DESC  LIMIT 1"));
            if (!CollectionUtils.isEmpty(refunds)) {
                DtsCarRentalRefund rentalRefund = refunds.get(0);
                WxPayRefundResult wxPayRefundResult = payService.carRetreat(dtsCarRental.getShopId(), "", forRetForm.getRefundNo(),
                        rentalRefund.getOutRefundNo(),
                        dtsCarRental.getTotalRent().doubleValue(),
                        cost.doubleValue(),
                        "/lease/dts/carRetreat/refund/notify",
                        "退车费用");
                log.info("【微信退款】wxPayRefundResult={}", JSON.toJSONString(wxPayRefundResult));
            }
        }
    }

    /**
     * 退车校验
     *
     * @param forRetForm
     */
    private void checke(ForRetForm forRetForm) {
        LambdaQueryWrapper<DtsCarRetreat> queryWrapper = new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getCarRentalId, forRetForm.getCarRentalId());
        DtsCarRental carRental = dtsCarRentalService.getById(forRetForm.getCarRentalId());
        int count = count(queryWrapper);
        if (count > 0) {
            DtsCarRetreat carRetreat = getOne(queryWrapper);
            if (carRetreat.getCost().doubleValue() < 0 && carRetreat.getIsPay() != 1 && StringUtils.isEmpty(forRetForm.getPaymentCode())) {
                throw new ApiException("租车费用尚未结清,请上传欠条或者结清费用!");
            }
            if (carRetreat.getCost().doubleValue() > 0 && carRental.getIsPayed() != 1 && StringUtils.isEmpty(forRetForm.getRcptCode())) {
                throw new ApiException("租车费用尚未结清,请上传领款单或收款码!");
            }
            if (carRetreat.getRetreatStatus() >= 2) {
                throw new ApiException("已经申请过退车,无需重复申请!");
            }
        }
    }


    /***
     * 退车审核
     * @param id
     * @param status
     * @param auditOpinion
     * @return
     */
    @Override
    public boolean checkBack(Long id, Byte status, String auditOpinion, Long shopId) {
        checked(id);
        DtsCarRetreat carRetreat = getById(id);
        Long carRentalId = carRetreat.getCarRentalId();
        DtsCarRental carRental = dtsCarRentalService.getById(carRentalId);
        //获取退车金额
        Double cost = getCost(id);
        String refundNo = "";
        int retreatStatus = 1;
        if (carRetreat.getStatus() != 1) {
            throw new ApiException("请选择状态为新申请的订单!");
        }
        Byte status1 = 0;
        if (status.intValue() == 1) {
            //审核通过
            examinationPassed(id);
            //关闭合同
            closeContract(carRentalId);
            //关闭扣费表
            closureUserDeduction(carRetreat.getUserId());
            //用户余额押金清零
            clearTheBal(carRetreat.getUserId());
            //清空用户账单表
            //clearUsrBill(carRetreat.getUserId());
            //退款
            Byte isPayed = carRental.getIsPayed();
            //禁用租车账号  guarantee
            disableGuarantee(carRetreat.getUserId());
            if (isPayed == 1) {
                if (cost > 0) {
                    String transactionId = getCarRetreatTransactionId(carRental.getOrderNumber());
                    refundNo = retCarRfnd(carRental, new BigDecimal(cost), transactionId, carRetreat.getAppId(), id, auditOpinion);
                    status1 = 4;
                } else {
                    if (carRetreat.getIsPay() != 1) {
                        status1 = 3;
                    } else {
                        status1 = 4;
                    }
                }
            } else {
                if (carRetreat.getIsPay() == 1 && cost < 0) {
                    status1 = 4;
                } else {
                    if (cost > 0) {
                        status1 = 2;
                    } else {
                        status1 = 3;
                    }
                }
            }
            retreatStatus = 2;
        } else {
            //审核驳回
            if (cost < 0 && 1 == carRetreat.getIsPay()) {
                String transactionId = getRetreatTransactionId(id);
                refundNo = retCarRfnd(carRental, new BigDecimal(cost), transactionId, carRetreat.getAppId(), id, auditOpinion);
            }
            retreatStatus = 0;
        }
        DtsCarRetreat dtsCarRetreat = new DtsCarRetreat();
        dtsCarRetreat.setId(id);
        dtsCarRetreat.setStatus(status1);
        dtsCarRetreat.setAuditOpinion(auditOpinion);
        dtsCarRetreat.setApprovalTime(new Date());
        dtsCarRetreat.setModifyBy(SecurityUtils.getUserId());
        dtsCarRetreat.setRefundOrder(refundNo);
        dtsCarRetreat.setRetreatStatus(retreatStatus);
        return updateById(dtsCarRetreat);
    }

    private void disableGuarantee(Long userId) {
        DtsUser dtsUser = dtsUserService.getById(userId);
        if (dtsUser == null) {
            throw new ApiException("租户信息有误，请联系管理员！");
        }
        guaranteeUserService.disableGuarantee(dtsUser.getIdCard());
    }

    /**
     * 获取退车是支付的订单号
     *
     * @param id
     * @return
     */
    private String getRetreatTransactionId(Long id) {
        return dtsCarRetreatMapper.getRetreatTransactionId(id);
    }


    /**
     * 获取租车是支付的订单号
     *
     * @param orderNumber
     * @return
     */
    private String getCarRetreatTransactionId(String orderNumber) {
        return dtsCarRetreatMapper.getCarRetreatTransactionId(orderNumber);
    }


    /**
     * 删除用户账单记录
     *
     * @param userId
     */
    private void clearUsrBill(Long userId) {
        dtsUserBillService.deleteByUserId(userId);
        sysUserTopupOrderService.deleteByUserId(userId);
    }


    /**
     * 获取退车时金额
     *
     * @param id 退车表单ID
     * @return 退车支付金额
     */
    private Double getCost(Long id) {
        DtsCarRetreat carRetreat = getById(id);
        //Double maintCost = dtsCarRetreatMapper.findMaintCost(id);
        Double cost = carRetreat.getCost().doubleValue();
//        if (maintCost != null) {
//            cost = cost - maintCost;
//        }
        return cost;
    }

    /**
     * 退车退款
     *
     * @param carRental 租车申请订单
     * @param amount    退款金额
     */
    private String retCarRfnd(DtsCarRental carRental, BigDecimal amount, String transactionId, String appId, Long id, String auditOpinion) {
        List<DtsCarRentalRefund> refunds = carRentalRefundService.list(new LambdaQueryWrapper<DtsCarRentalRefund>()
                .eq(DtsCarRentalRefund::getOrderId, carRental.getId())
                .last("ORDER BY created DESC  LIMIT 1"));
        if (!CollectionUtils.isEmpty(refunds)) {
            String refundNo = IdWorker.getId() + "";
            payService.carRetreat(carRental.getShopId(), appId, refundNo,
                    transactionId,
                    carRental.getTotalRent().doubleValue(),
                    amount.abs().doubleValue(),
                    "/lease/dts/carRetreat/refund/notify",
                    auditOpinion);

            DtsCarRetreat dtsCarRetreat = new DtsCarRetreat();
            dtsCarRetreat.setId(id);
            dtsCarRetreat.setIsPay((byte) 0);
            updateById(dtsCarRetreat);
            return refundNo;
        }
        return null;
    }


    /**
     * 审核钱参数校验
     *
     * @param id
     */
    private void checked(Long id) {
        DtsCarRetreat carRetreat = getById(id);
        if (carRetreat == null)
            throw new MyException("参数异常,当前退车订单不存在!");
        if (carRetreat.getStatus().intValue() == 3)
            throw new MyException("当前退车订单已完成,无需重复操作!");
        if (carRetreat.getStatus().intValue() == 2)
            throw new MyException("当前退车订单已审核,请上传结算凭证!");
    }

    /***
     * 清零用户余额
     * @param id
     */
    private void clearUserBalance(Long id) {
        //用户租车信息
        DtsCarRental dtsCarRental = dtsCarRentalService.getById(id);
        Long userId = dtsCarRental.getUserId();
        DtsUser dtsUser = new DtsUser();
        dtsUser.setId(userId);
        dtsUser.setBalance(new BigDecimal("0"));
        dtsUserService.updateById(dtsUser);
    }


    /***
     * 结算用户费用
     * @param id
     * @param rfndCertificate
     * @return
     */
    @Override
    public boolean userRefund(Long id, String rfndCertificate) {
        DtsCarRetreat carRetreat = getById(id);
        boolean flag = true;
        if (carRetreat.getStatus() == 2 || carRetreat.getStatus() == 3) {
            flag = false;
        }
        if (flag) {
            throw new MyException("请先去审核!");
        }
        Long userId = carRetreat.getUserId();
        carRetreat.setRfndCertificate(rfndCertificate);
        //更新用户余额
        updateUserBalance(userId);
        //关闭租车订单
        cloCarRentalOrdr(carRetreat.getCarRentalId());
        carRetreat.setStatus((byte) 4);
        //逻辑删除担保信息
        colGuaranteeUser(carRetreat.getUserId());
        return updateById(carRetreat);
    }

    /**
     * 维修费用
     *
     * @param maintIds
     */
    public BigDecimal getRepairFees(List<Long> maintIds) {
        BigDecimal maintSum = new BigDecimal(0);
        if (CollectionUtils.isEmpty(maintIds)) {
            return maintSum;
        }
        if (!CollectionUtils.isEmpty(maintIds)) {
            List<RepairMaint> repairMaints = repairMaintService.listByIds(maintIds);
            if (!CollectionUtils.isEmpty(repairMaints)) {
                for (RepairMaint repairMaint : repairMaints) {
                    maintSum = maintSum.add(repairMaint.getPrice());
                }
            }
        }
        return maintSum;
    }

    /***
     * 逻辑删除担保信息
     * @param userId
     */
    private void colGuaranteeUser(Long userId) {
        DtsUser dtsUser = dtsUserService.getById(userId);
        if (dtsUser == null)
            throw new MyException("获取不到租车用户，请联系管理员！");
        List<GuaranteeUser> list = guaranteeUserService.list(new LambdaQueryWrapper<GuaranteeUser>()
                .eq(GuaranteeUser::getIdCard, dtsUser.getIdCard()));
        if (CollectionUtils.isEmpty(list))
            return;
        list.forEach(user -> user.setStatus((byte) 0));
        guaranteeUserService.updateBatchById(list);
    }

    /***
     * 查询今日退车量
     * @return
     */
    @Override
    public Map<String, Integer> returnAmount(Long shopId) {
        return dtsCarRetreatMapper.returnAmount(shopId);
    }


    /**
     * 退车清单导出
     *
     * @param response
     */
    @Override
    public void export(HttpServletResponse response, String idCard, String mobile, String realName, Long siteId, Long shopId) {
        Long userId = SecurityUtils.getUserId();
        SysUser user = sysUserService.getById(userId);
        if (user == null || user.getCommunityId() == null) {
            return;
        }
        Long communityId = null;
        if (user.getCommunityId() != 1L) {
            communityId = user.getCommunityId();
        }
        List<RetreatDetailed> retreatDetaileds = dtsCarRetreatMapper.findRetreatDetailed(idCard, mobile, realName, siteId, communityId, shopId); //退车明细
        if (!CollectionUtils.isEmpty(retreatDetaileds)) {
            for (RetreatDetailed retreatDetailed : retreatDetaileds) {
                if (StringUtils.isEmpty(retreatDetailed.getSiteName()) && retreatDetailed.getGuaranteeCompanyId() != null) {
                    GuaranteeCompany guaranteeCompany = guaranteeCompanyService.getById(retreatDetailed.getGuaranteeCompanyId());
                    retreatDetailed.setSiteName(guaranteeCompany != null ? guaranteeCompany.getName() : "");
                }
                /*if (!StringUtils.isEmpty(retreatDetailed.getRfndCertificate())) {
                    retreatDetailed.setRfndCertificate("已完结状态");
                } else {
                    retreatDetailed.setRfndCertificate("进行中还有退车");
                }*/
                BigDecimal price = repairMaintService.getPriceByRetreatId(retreatDetailed.getId());
                if (price == null) {
                    price = new BigDecimal("0");
                }
                retreatDetailed.setRepairMaint(price);
            }
            log.info("【退车明细】{}", JSON.toJSONString(retreatDetaileds));
        }
        //表单到出
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(MyDateUtils.getCurDt() + "退车清单", MyDateUtils.getCurDt()), RetreatDetailed.class, retreatDetaileds);
        try {
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(MyDateUtils.getCurDt() + "租车明细.xls", "UTF-8"));
            ServletOutputStream os = response.getOutputStream();
            workbook.write(os);
            os.close();
            workbook.close();
        } catch (IOException e) {
            log.error("【导出今日租车明细,错误】{}", JSON.toJSONString(e));
        }

    }

    /***
     * 导出退车欠款未结清记录
     */
    @Override
    public void export2(HttpServletResponse response, Long shopId) {
        Long userId = SecurityUtils.getUserId();
        SysUser user = sysUserService.getById(userId);
        if (user == null || user.getCommunityId() == null) {
            return;
        }
        Long communityId = null;
        if (user.getCommunityId() != 1L) {
            communityId = user.getCommunityId();
        }
        List<RetreatDetailed> retreatDetaileds = dtsCarRetreatMapper.findRetreatDetailed2(communityId, shopId); //导出退车欠款未结清记录
        if (!CollectionUtils.isEmpty(retreatDetaileds)) {
            for (RetreatDetailed retreatDetailed : retreatDetaileds) {
                if (StringUtils.isEmpty(retreatDetailed.getSiteName()) && retreatDetailed.getGuaranteeCompanyId() != null) {
                    GuaranteeCompany guaranteeCompany = guaranteeCompanyService.getById(retreatDetailed.getGuaranteeCompanyId());
                    retreatDetailed.setSiteName(guaranteeCompany != null ? guaranteeCompany.getName() : "");
                }
                /*if (!StringUtils.isEmpty(retreatDetailed.getRfndCertificate())) {
                    retreatDetailed.setRfndCertificate("已完结状态");
                } else {
                    retreatDetailed.setRfndCertificate("进行中还有退车");
                }*/
                BigDecimal price = repairMaintService.getPriceByRetreatId(retreatDetailed.getId());
                if (price == null) {
                    price = new BigDecimal("0");
                }
                retreatDetailed.setRepairMaint(price);
            }
            log.info("【导出退车欠款未结清记录】{}", JSON.toJSONString(retreatDetaileds, true));
        }
        //表单到出
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(MyDateUtils.getCurDt() + "导出退车欠款未结清记录", MyDateUtils.getCurDt()), RetreatDetailed.class, retreatDetaileds);
        try {
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(MyDateUtils.getCurDt() + "租车明细.xls", "UTF-8"));
            ServletOutputStream os = response.getOutputStream();
            workbook.write(os);
            os.close();
            workbook.close();
        } catch (Exception e) {
            log.error("【导出退车欠款未结清记录,错误】{}", JSON.toJSONString(e, true));
        }
    }

    /**
     * 退车支付回调
     *
     * @param outTradeNo
     * @param transactionId
     */
    @Override
    public void payNotify(String outTradeNo, String transactionId, String appId) {
        log.info("退车支付回调操作：outTradeNo：{}， transactionId{}", outTradeNo, transactionId);
        DtsCarRetreat dtsCarRetreat = getOne(new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getPayOrder, outTradeNo));
        if (dtsCarRetreat == null) {
            return;
        }
        if (1 == dtsCarRetreat.getIsPay()) {
            return;
        }
        //用户余额清零
        //clearTheBal(dtsCarRetreat.getUserId());
        if (dtsCarRetreat != null) {
            DtsCarRetreat carRetreat = new DtsCarRetreat();
            carRetreat.setId(dtsCarRetreat.getId());
            carRetreat.setIsPay((byte) 1);
            carRetreat.setTransactionId(transactionId);
            carRetreat.setPayTime(new Date());
            carRetreat.setAppId(appId);
            updateById(carRetreat);
        }
    }

    /**
     * 退车退款回调
     *
     * @param outRefundNo
     */
    @Override
    public void refundNotify(String outRefundNo) {
        DtsCarRetreat dtsCarRetreat = getOne(new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getRefundOrder, outRefundNo));
        if (1 == dtsCarRetreat.getIsRefund()) {
            return;
        }
        //用户余额清零
        //clearTheBal(dtsCarRetreat.getUserId());
        if (dtsCarRetreat != null) {
            DtsCarRetreat carRetreat = new DtsCarRetreat();
            carRetreat.setId(dtsCarRetreat.getId());
            carRetreat.setRetreatStatus((byte) 1);
            carRetreat.setIsRefund((byte) 1);
            carRetreat.setRefundTime(new Date());
            updateById(carRetreat);
        }
        //关闭合同
//        Long carRentalId = dtsCarRetreat.getCarRentalId();
//        closeContract(carRentalId);
        //关闭扣费表
//        closureUserDeduction(dtsCarRetreat.getUserId());
    }

    @Override
    public boolean inspect(Long carRentalId) {
        DtsCarRetreat carRetreat = getOne(new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getCarRentalId, carRentalId));
        DtsCarRental dtsCarRental = dtsCarRentalService.getById(carRentalId);
        if (0 != dtsCarRental.getStopRep()){
            throw new ApiException("您已报停租车,请先回复后,在申请退车!");
        }
        if (carRetreat != null && carRetreat.getStatus() == 1){
            throw new ApiException("已有退车订单, 请联系管理员审核");
        }
        DtsCarTransfer carTransfer = dtsCarTransferService.getOne(new LambdaQueryWrapper<DtsCarTransfer>()
                .eq(DtsCarTransfer::getCarRentalId, carRentalId)
                .last("LIMIT 1"));
        if (carTransfer != null) {
            Byte status = carTransfer.getStatus();
            if (status.intValue() != 2) {
                throw new ApiException("您目前还有尚未完成的换车订单！");
            }
        }
        return true;
    }

    /**
     * 关闭合同
     *
     * @param carRentalId
     */
    private void closeContract(Long carRentalId) {
        DtsCarRental dtsCarRental = new DtsCarRental();
        dtsCarRental.setStatus((byte) 4);
        dtsCarRental.setRetreatStatus((byte) 2);
        dtsCarRental.setId(carRentalId);
        dtsCarRental.setTerminationDate(new Date());
        dtsCarRentalService.updateById(dtsCarRental);
    }

    /**
     * 用户余额清零
     */
    private void clearTheBal(Long userId) {
        dtsUserService.clearTheBal(userId);
    }


    /***
     * 关闭租车订单
     * @param carRentalId 租车申请ID
     */
    private void cloCarRentalOrdr(Long carRentalId) {
        DtsCarRental dtsCarRental = new DtsCarRental();
        dtsCarRental.setId(carRentalId);
        dtsCarRental.setStatus((byte) 4);
        dtsCarRental.setRetreatStatus((byte) 2);
        dtsCarRentalService.updateById(dtsCarRental);
    }


    /***
     * 退车用户余额清零
     * @param userId
     */
    private void updateUserBalance(Long userId) {
        DtsUser dtsUser = new DtsUser();
        dtsUser.setId(userId);
        dtsUser.setBalance(new BigDecimal(0));
        dtsUser.setDeposit(new BigDecimal(0));
        dtsUserService.updateDtsUser(dtsUser);
    }


    /***
     * 关闭扣费表
     * @param userId
     */
    private void closureUserDeduction(Long userId) {
        //DtsCarRetreat dtsCarRetreat = getById(id);
        dtsUserDeductionService.remove(new LambdaQueryWrapper<DtsUserDeduction>()
                .eq(DtsUserDeduction::getUserId, userId));
    }


    /***
     * 审核通过 更新车辆信息
     * @param id
     */
    private void examinationPassed(Long id) {
        DtsCarRetreat carRetreat = getById(id);
        Long repairCodeId = carRetreat.getRepairCodeId();
        if (repairCodeId != null) {
            //检查车辆是否有异常
            List<RepairMaint> repairMaints = dtsCarRetreatMaintService.getRepairMaintByTransferId(id);
            StringBuffer unusualLocation = new StringBuffer("");
            Byte vehicleStatus = (byte) 1;
            if (!CollectionUtils.isEmpty(repairMaints)) {
                for (int i = 0; i < repairMaints.size(); i++) {
                    RepairMaint repairMaint = repairMaints.get(i);
                    if (i != repairMaints.size() - 1) {
                        unusualLocation.append(i + 1 + "." + repairMaint.getName()).append("损坏, ");
                    } else {
                        unusualLocation.append(i + 1 + "." + repairMaint.getName()).append("损坏;");
                    }
                }
                vehicleStatus = 2;
            }
            //更新车辆信息
            RepairCode repairCode = repairCodeService.getById(repairCodeId);
            repairCode.setVehicleStatus(vehicleStatus);
            repairCode.setUnusualLocation(unusualLocation.toString());
            repairCode.setRentUser(null);
            repairCode.setVehicleBelongs(carRetreat.getCommunityId());
            repairCodeService.updateByPrimaryKeySelective(repairCode);
        }
    }

    /***
     * 退车验证
     * @param forRetForm
     */
    private void checkedAppForRet(ForRetForm forRetForm) {
        int count = count(new LambdaQueryWrapper<DtsCarRetreat>().eq(DtsCarRetreat::getCarRentalId, forRetForm.getCarRentalId()));
        if (count > 0) {
            throw new MyException("退出申请已提交,请联系管理员审核");
        }
    }

    /**
     * 中间表插入数据
     *
     * @param maintIds
     */
    private void saveDtsCarRetreatMaint(List<Long> maintIds, Long carRetreatId) {
        if (CollectionUtils.isEmpty(maintIds)) {
            return;
        }
        LambdaQueryWrapper<DtsCarRetreatMaint> queryWrapper = new LambdaQueryWrapper<DtsCarRetreatMaint>()
                .eq(DtsCarRetreatMaint::getCarRetreatId, carRetreatId);
        int count = dtsCarRetreatMaintService.count(queryWrapper);
        if (count > 0) {
            dtsCarRetreatMaintService.remove(queryWrapper);
        }
        List<DtsCarRetreatMaint> carRetreatMaints = new ArrayList<>(maintIds.size());
        for (Long maintId : maintIds) {
            carRetreatMaints.add(new DtsCarRetreatMaint(IdWorker.getId(), carRetreatId, maintId));
        }
        dtsCarRetreatMaintService.saveBatch(carRetreatMaints);
    }

    /***
     * 退车申请
     * @param forRetForm
     * @return
     */
    private DtsCarRetreat getDtsCarRetreat(ForRetForm forRetForm) {
        DtsCarRental dtsCarRental = getDtsCarRental(forRetForm.getCarRentalId());
        if (dtsCarRental == null) {
            throw new ApiException("参数无效");
        }
        Long id = null;
        LambdaQueryWrapper<DtsCarRetreat> queryWrapper = new LambdaQueryWrapper<DtsCarRetreat>()
                .eq(DtsCarRetreat::getCarRentalId, forRetForm.getCarRentalId());
        int count = count(queryWrapper);
        if (count > 0) {
            DtsCarRetreat dtsCarRetreat1 = getOne(queryWrapper);
            id = dtsCarRetreat1.getId();
        } else {
            id = IdWorker.getId();
        }
        DtsCarRetreat dtsCarRetreat = new DtsCarRetreat();
        BeanUtils.copyProperties(forRetForm, dtsCarRetreat);
        dtsCarRetreat.setId(id);
        dtsCarRetreat.setAdminId(SecurityUtils.getUserId());
        dtsCarRetreat.setCommunityId(getCommunityId(SecurityUtils.getUserId()));
        dtsCarRetreat.setRepairCodeId(dtsCarRental.getRepairCodeId());
        dtsCarRetreat.setUserId(dtsCarRental.getUserId());
        dtsCarRetreat.setCreated(new Date());
        dtsCarRetreat.setStatus((byte) 1);
        dtsCarRetreat.setGuaranteeCompanyId(dtsCarRental.getGuaranteeCompanyId());
        dtsCarRetreat.setRentalBalance(getUserbalance(forRetForm.getCarRentalId()));
        return dtsCarRetreat;
    }


    /***
     * 用户余额
     * @param carRentalId
     * @return
     */
    private BigDecimal getUserbalance(Long carRentalId) {
        return dtsCarRentalService.getUserbalance(carRentalId);
    }


    private DtsCarRental getDtsCarRental(Long id) {
        return dtsCarRentalService.getById(id);
    }


    /***
     * 获取站点ID
     * @param userId
     * @return
     */
    private Long getCommunityId(Long userId) {
        DtsUser dtsUser = dtsUserService.getById(userId);
        if (dtsUser == null) {
            throw new MyException("参数无效");
        }
        return dtsUser.getCommunityId();
    }

    /**
     * 获取配件列表
     *
     * @param repairMaintIds
     * @return
     */
    private List<RepairMaint> getRepairMaintList(List<Long> repairMaintIds) {
        if (CollectionUtils.isEmpty(repairMaintIds)) {
            return new ArrayList<RepairMaint>();
        }
        List<RepairMaint> maintList = repairMaintService.list(new LambdaQueryWrapper<RepairMaint>()
                .eq(RepairMaint::getStatus, 1)
                .in(RepairMaint::getId, repairMaintIds));
        return maintList;
    }


}
